import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;


public class VideoFile {
	private int width;
	private int height;
	private double fps = 24;
	private long totalFrameNumber;
	private double totalPlayTime;        //unit is second
	private int frameSize;
	private double frameDuration;        //Duration per frame in millisecond
	
	private RandomAccessFile videoFile;
	private byte[] rawBuffer;
	private long  frameCounter;
	
	public VideoFile(String fileName){
		this(fileName, 320, 240);
	} 
	
	public VideoFile(String fileName, int width, int height){
	    try {
		    File file = new File(fileName);
		    videoFile = new RandomAccessFile(file, "r");
		    
		    //Init all properties
		    this.width = width;
		    this.height = height;
			long size = file.length();
			frameSize = width * height * 3;
			totalFrameNumber = size/frameSize;
			totalPlayTime = totalFrameNumber/fps; 
			frameDuration = 1000/(double)fps;
			rawBuffer = new byte[frameSize];
			frameCounter = 0;
		} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
		}
	}

	public boolean readNextFrame(VideoFrame frame){
		
		try {
			//Read raw data
		    int offset = 0;
	        int numRead = 0;
	        while (offset < frameSize && (numRead=videoFile.read(rawBuffer, offset, frameSize-offset)) >= 0) {
	            offset += numRead;
	        }
	        //Generate Buffered Image
	        int ind = 0;
			for(int y = 0; y < height; y++){
		
				for(int x = 0; x < width; x++){
			 
					//byte a = 0;
					byte r = rawBuffer[ind];
					byte g = rawBuffer[ind+height*width];
					byte b = rawBuffer[ind+height*width*2]; 
					
					int pix = 0xff000000 | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
					//int pix = ((a << 24) + (r << 16) + (g << 8) + b);
					frame.image.setRGB(x,y,pix);
					ind++;
				}
			}
			//Generate the corresponding time stamp
//			long timePeriodNo = frameCounter / fps;
//			long timePeriodStep = frameCounter % fps;
//			frame.timeStamp = (long) (1000 * timePeriodNo + timePeriodStep * frameDuration);
			frame.timeStamp = (long) (frameCounter * frameDuration);
			++frameCounter;
	        
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
        return true;
	}
	
	/********************************************
	 * Set the frame position, frame is zero-based
	 * @param time
	 */
	public void setFramePosition(long frames){
		try {
			videoFile.seek(frames * frameSize);
			frameCounter = frames;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}
	
	/********************************************
	 * Set the time position, time is in milliseconds
	 * @param time
	 */
	public void setTimePosition(long milliseconds){
		long period = milliseconds / 1000;
		long delta = (long) (milliseconds % 1000 / frameDuration);
		long framePosition = (long) (fps * period + delta);
		setFramePosition(framePosition);
	}

	
	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

	public long getTotalFrameNumber() {
		return totalFrameNumber;
	}

	public double getTotalPlayTime() {
		return totalPlayTime;
	}

	public double getFps() {
		return fps;
	}
	
	
}

